package com.fh.modules.dbms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fh.common.exception.Assert;
import com.fh.common.util.DateUtils;
import com.fh.common.util.StringUtils;
import com.fh.common.web.impl.AbstractServiceImpl;
import com.fh.db.DbColumn;
import com.fh.db.DbIndex;
import com.fh.db.DbIndexColumn;
import com.fh.db.DbTable;
import com.fh.modules.dbms.entity.DbmsTable;
import com.fh.modules.dbms.entity.DbmsTableColumn;
import com.fh.modules.dbms.entity.DbmsTableIndex;
import com.fh.modules.dbms.entity.DbmsTableIndexColumn;
import com.fh.modules.dbms.mapper.DbmsTableMapper;
import com.fh.modules.dbms.model.CompareResultModel;
import com.fh.modules.dbms.model.TableCompareResult;
import com.fh.modules.dbms.service.IDbmsTableColumnService;
import com.fh.modules.dbms.service.IDbmsTableIndexColumnService;
import com.fh.modules.dbms.service.IDbmsTableIndexService;
import com.fh.modules.dbms.service.IDbmsTableService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author qiujunda
 * @Date 23/07/2020
 * @Description
 */
@Service
public class DbmsTableServiceImpl  extends AbstractServiceImpl<DbmsTableMapper, DbmsTable> implements IDbmsTableService {
    @Autowired
    private IDbmsTableColumnService dbmsTableColumnService;
    @Autowired
    private IDbmsTableIndexService dbmsTableIndexService;
    @Autowired
    private IDbmsTableIndexColumnService dbmsTableIndexColumnService;

    @Override
    @Transactional
    public DbmsTable addOrUpdateDbmsTable(DbTable dbTable,Long sourceId,String collectSid) {
        DbmsTable dbmsTableOld=queryDbmsTable(sourceId,dbTable.getTableName());
        boolean updateTableOther=false;
        if(dbmsTableOld==null){
            dbmsTableOld=new DbmsTable();
            updateTableOther=true;
        }else if(!DateUtils.formatTime(dbTable.getLastDdlTime()).equals(DateUtils.formatTime(dbmsTableOld.getLastDdlTime()))){
            //根据表的最近更新时间判断是否需要更新索引，字段，触发器等信息
            updateTableOther=true;
        }
        BeanUtils.copyProperties(dbTable,dbmsTableOld);
        dbmsTableOld.setSourceId(sourceId);
        dbmsTableOld.setCollectSid(collectSid);
        //是否需要更新表的索引，字段，触发器等信息
        if(updateTableOther){
            List<DbColumn> dbColumnList=dbTable.getColumns();
            List<DbIndex> dbIndexList=dbTable.getIndexs();
            dbmsTableOld.setColumnNum(dbColumnList.size());
            dbmsTableOld.setIndexNum(dbIndexList.size());
            this.saveOrUpdate(dbmsTableOld);
            dbmsTableColumnService.deleteByTableId(dbmsTableOld.getId());
            for(DbColumn dbColumn:dbColumnList){
                DbmsTableColumn dbmsTableColumn=new DbmsTableColumn();
                BeanUtils.copyProperties(dbColumn,dbmsTableColumn);
                dbmsTableColumn.setTableId(dbmsTableOld.getId());
                dbmsTableColumnService.save(dbmsTableColumn);
            }

            dbmsTableIndexService.deleteByTableId(dbmsTableOld.getId());
            for(DbIndex dbIndex:dbIndexList){
                DbmsTableIndex dbmsTableIndex=new DbmsTableIndex();
                BeanUtils.copyProperties(dbIndex,dbmsTableIndex);
                dbmsTableIndex.setTableId(dbmsTableOld.getId());
                List<DbIndexColumn> dbIndexColumnList=dbIndex.getDbIndexColumn();
                dbmsTableIndex.setColumnNum(dbIndexColumnList.size());
                dbmsTableIndexService.save(dbmsTableIndex);
                for(DbIndexColumn dbIndexColumn:dbIndexColumnList){
                    DbmsTableIndexColumn dbmsTableIndexColumn=new DbmsTableIndexColumn();
                    dbmsTableIndexColumn.setColumnName(dbIndexColumn.getColumnName());
                    dbmsTableIndexColumn.setColumnPosition(dbIndexColumn.getColumnPosition());
                    dbmsTableIndexColumn.setIndexId(dbmsTableIndex.getId());
                    dbmsTableIndexColumnService.save(dbmsTableIndexColumn);
                }
            }

        }else{
            this.updateById(dbmsTableOld);
        }
        return dbmsTableOld;
    }

    @Override
    public TableCompareResult compareTable(DbmsTable dbmsTable,DbmsTable dbmsTableDes){
        TableCompareResult tableCompareResult;
        boolean indexResult,columnResult,result;
        if(dbmsTableDes==null){
            tableCompareResult=new TableCompareResult(dbmsTable.getTableName());
        }else{
            tableCompareResult=new TableCompareResult(dbmsTable.getTableName(),dbmsTableDes.getTableName());
            columnResult=dbmsTable.getColumnNum()==dbmsTableDes.getColumnNum();
            indexResult=dbmsTable.getIndexNum()==dbmsTableDes.getIndexNum();
            if(columnResult){
                columnResult=dbmsTableColumnService.compareTableColumn(dbmsTable.getId(),dbmsTableDes.getId());
            }
            if(indexResult){
                indexResult=dbmsTableIndexService.compareTableIndex(dbmsTable.getId(),dbmsTableDes.getId());
            }
            result=columnResult&&indexResult;
            tableCompareResult.setColumnResult(columnResult);
            tableCompareResult.setIndexResult(indexResult);
            tableCompareResult.setResult(result);
            tableCompareResult.setLastDdlTime2(dbmsTableDes.getLastDdlTime());
        }
        tableCompareResult.setLastDdlTime1(dbmsTable.getLastDdlTime());
        return tableCompareResult;
    }

    @Override
    public List<TableCompareResult> compareTable(Long sourceId1, Long sourceId2, String tableName, Integer diff) {
        List<TableCompareResult> tableCompareResults=new ArrayList<>();
        List<DbmsTable> dbmsTableList=this.queryDbmsTables(sourceId1,tableName);
        for(DbmsTable dbmsTable:dbmsTableList){
            DbmsTable dbmsTableDes=this.queryDbmsTable(sourceId2,dbmsTable.getTableName());
            TableCompareResult tableCompareResult=this.compareTable(dbmsTable,dbmsTableDes);
            if(diff==null||(diff==1&&tableCompareResult.isResult())||(diff==0&&!tableCompareResult.isResult())){
                tableCompareResults.add(tableCompareResult);
            }
        }
        return tableCompareResults;
    }

    @Override
    public CompareResultModel queryTableColumnContent(DbmsTable dbmsTable1,DbmsTable dbmsTable2) {
        return new CompareResultModel(this.queryTableColumnStr(dbmsTable1),this.queryTableColumnStr(dbmsTable2));
    }

    @Override
    public CompareResultModel queryTableIndexContent(DbmsTable dbmsTable1,DbmsTable dbmsTable2) {
        return new CompareResultModel(this.queryTableIndexStr(dbmsTable1),this.queryTableIndexStr(dbmsTable2));
    }


    @Override
    public DbmsTable queryDbmsTable(Long sourceId, String tableName){
        Assert.isTrue(StringUtils.isEmpty(tableName),"表名不存在");
        QueryWrapper<DbmsTable> queryWrapper = new QueryWrapper<DbmsTable>();
        queryWrapper.eq("source_id", sourceId).eq("table_name", tableName).eq("del_flag",0);
        return this.getOne(queryWrapper);
    }

    public String queryTableColumnStr(DbmsTable dbmsTable){
        StringBuilder tableStr=new StringBuilder(256);
        if(dbmsTable!=null){
            tableStr.append(dbmsTable.toString()+"\n");
            List<DbmsTableColumn> dbmsTableColumns=dbmsTableColumnService.queryTableColumns(dbmsTable.getId());
            dbmsTableColumns.forEach(dbmsTableColumn -> {
                tableStr.append(" "+dbmsTableColumn.toString()+"\n");
            });
        }
        return tableStr.toString();
    }

    public String queryTableIndexStr(DbmsTable dbmsTable){
        StringBuilder tableStr=new StringBuilder(256);
        if(dbmsTable!=null){
            tableStr.append(dbmsTable.toString()+"\n");
            List<DbmsTableIndex> dbmsTableIndexList=dbmsTableIndexService.queryDbmsTableIndex(dbmsTable.getId());
            dbmsTableIndexList.forEach(dbmsTableIndex -> {
                tableStr.append(" "+dbmsTableIndex.toString()+"\n");
                List<DbmsTableIndexColumn> dbmsTableIndexColumnList=dbmsTableIndexColumnService.queryTableIndexColumns(dbmsTableIndex.getId());
                dbmsTableIndexColumnList.forEach(dbmsTableIndexColumn -> {
                    tableStr.append("  "+dbmsTableIndexColumn.toString()+"\n");
                });
            });
        }
        return tableStr.toString();
    }

    /**
     * 根据表名查询所有实体
     * @param sourceId
     * @param tableName 非必填
     * @return
     */
    public List<DbmsTable> queryDbmsTables(Long sourceId, String tableName){
        QueryWrapper<DbmsTable> queryWrapper = new QueryWrapper<DbmsTable>();
        queryWrapper.eq("source_id", sourceId).eq("del_flag",0);
        if(StringUtils.isNotEmpty(tableName)){
            queryWrapper.eq("table_name", tableName);
        }
        queryWrapper.orderByDesc("last_ddl_time");
        return this.list(queryWrapper);
    }
}
